﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Xyz.Web.Reservation.BookingService;
using Xyz.Web.Reservation.Repositories;
using Xyz.Web.Reservation.Models;


namespace Xyz.Web.Reservation.Controllers
{

    //todo: 
    // static data for booking  cardpayment memberpayment  member
    
    public class ShoppingcartController : Controller
    {
        

        AddonRepository addonRep = new AddonRepository();
        SeatRepository seatRep = new SeatRepository();
        BookingRepository bookingRep = new BookingRepository();
        FlightRepository flightRep = new FlightRepository();

        public ActionResult Seat()
        {

            LoadData();
           
           BookingModel bm = (BookingModel)Session["booking"] ;
           string seatTypeCode = (string)Session["seatType"];
           List<TicketModel> tickets = bm.Tickets;
           for (int i = 0; i < tickets.Count(); i++)
           {
               //get viewdata avaliable seat for seatTypeCode

              List<SeatModel> seats = seatRep.GetAvaliableAircraftSeatByFlightIdSeatTypeCode(tickets[i].FlightId, seatTypeCode).ToModel();
              ViewData["allSeats" + i] = new List<string>(from c in seats orderby c.SeatNo select c.SeatNo);
              
           }
           return View(bm);

        }

         [HttpPost]
        public ActionResult Seat(FormCollection collection)
        {
           
         //validate the seat here
            BookingModel bm = (BookingModel)Session["booking"] ;
            string seatTypeCode = (string)Session["seatType"];
            List<TicketModel> tickets = bm.Tickets;
            List<string> errorList = new List<string>();
          

            Boolean hasError = false;

            List<string> departureSeatSelected = new List<string>();
            List<string> returnSeatSelected = new List<string>();
                      
                 for (int i = 0; i < tickets.Count(); i++)
                 {
                     List<SeatModel> seats = seatRep.GetAvaliableAircraftSeatByFlightIdSeatTypeCode(tickets[i].FlightId, seatTypeCode).ToModel();
                    List<string> arrivalSeatsNo = new List<string>(from c in seats orderby c.SeatNo select c.SeatNo);

                    ViewData["allSeats" + i] = arrivalSeatsNo;
                     String seatCode = collection["SeatCode" + i].ToUpper(); //everything covert to uppercase
                   
                     //get seat model
                     AircraftDTO aircraftDto = seatRep.getAircraftByFlightId (tickets[i].FlightId);
                     SeatModel seatModel = seatRep.getAircraftSeatByAircraftIdSeatCode(aircraftDto.AircraftId, seatCode).ToModel();
                     if (seatModel == null)
                     {
                         errorList.Add("Seat Code " + seatCode + " is Invalid!");
                         hasError = true;
                     }
                     else if (!arrivalSeatsNo.Contains(seatCode))
                     {//check avaliable again
                         errorList.Add("Seat Code " + seatCode + " is Selected by Other Customer!");
                         hasError = true;
                     }

                     //check if seat duplicated
                     else
                     {
                         if (tickets[i].isDeparture == true)
                         {
                             if (departureSeatSelected.Contains(seatModel.SeatNo))
                             {
                                 errorList.Add("Cannot select same seat for departure trip, please choose another one");
                                 hasError = true;
                             }
                             else
                             {
                                 departureSeatSelected.Add(seatModel.SeatNo);
                                 errorList.Add("");
                                 //map seatDTO to model, set model inside bm
                                 FlightSeatModel flightSeatModel = new FlightSeatModel();
                                 flightSeatModel.AircraftSeatId = seatModel.AircraftSeatId;
                                 flightSeatModel.FlightId = tickets[i].FlightId;
                                 flightSeatModel.Status = "blocked";

                                 bm.Tickets[i].Seat = seatModel;
                                 bm.Tickets[i].FlightSeat = flightSeatModel;
                                 tickets[i].SeatCode = seatCode;
                             }
                         }
                         else //for returnTrip
                         {
                             if (returnSeatSelected.Contains(seatModel.SeatNo))
                             {
                                 errorList.Add("Cannot select same seat for return trip, please choose another one");
                                 hasError = true;
                             }
                             else
                             {
                                 returnSeatSelected.Add(seatModel.SeatNo);
                                 errorList.Add("");
                                 //map seatDTO to model, set model inside bm
                                 FlightSeatModel flightSeatModel = new FlightSeatModel();
                                 flightSeatModel.AircraftSeatId = seatModel.AircraftSeatId;
                                 flightSeatModel.FlightId = tickets[i].FlightId;
                                 flightSeatModel.Status = "blocked";

                                 bm.Tickets[i].Seat = seatModel;
                                 bm.Tickets[i].FlightSeat = flightSeatModel;
                                 tickets[i].SeatCode = seatCode;
                             }

                         }
                         
                     }

                 }
                

                 if (hasError)
                 {
                     ViewData["seatError"] = errorList;
                     return View(bm);
                 }
                 else
                 {
                     foreach (TicketModel tm in tickets)
                     {
                         tm.FlightSeat = seatRep.SaveBlockFlightSeat(Mapper.FromModel(tm.FlightSeat)).ToModel(); //save blocked seat to db
                     }
                     bm.Tickets = tickets;
                     Session["booking"] = bm;
                     return RedirectToAction("Addon", "Shoppingcart");
                 }
          
        }
        

        
        public ActionResult Addon()
        {

            BookingModel bm = (BookingModel)Session["booking"];
           
            ViewData["LuggServices"] = addonRep.GetAllServicesByServiceCategoryCode("LUGG").ToModel();
            ViewData["InsuServices"] = addonRep.GetAllServicesByServiceCategoryCode("INSU").ToModel();
            ViewData["MealServices"] = addonRep.GetAllServicesByServiceCategoryCode("MEAL").ToModel();

            return View(bm);
        }

       

        [HttpPost]
        public ActionResult Addon(FormCollection collection)
        {

            List<TicketModel> ticketsList = ((BookingModel)Session["booking"]).Tickets;

                
            for (int i = 0; i < ticketsList.Count; i++) 
	        {
                List<PassengerServiceModel> Services = new List<PassengerServiceModel>();
                if (collection["LuggService" + i] != null && collection["LuggService" + i].Length > 0)
                {
                   
                    string serviceCode = collection["LuggService" + i];
                    ServiceModel sm = addonRep.getServiceByServiceCode(serviceCode).ToModel();
                    Services.Add(new PassengerServiceModel() {ServiceCode = sm.ServiceCode, Price = sm.Price, ServiceDescription = sm.ServiceDescription});
                }

                if (collection["InsuService" + i] != null && collection["InsuService" + i].Length > 0)
                {

                    string serviceCode = collection["InsuService" + i];
                    ServiceModel sm = addonRep.getServiceByServiceCode(serviceCode).ToModel();
                    Services.Add(new PassengerServiceModel() { ServiceCode = sm.ServiceCode, Price = sm.Price, ServiceDescription = sm.ServiceDescription });
                   
                }
                if (collection["MealService" + i] != null && collection["MealService" + i].Length > 0)
                {

                    string serviceCode = collection["MealService" + i];
                    ServiceModel sm = addonRep.getServiceByServiceCode(serviceCode).ToModel();
                    Services.Add(new PassengerServiceModel() { ServiceCode = sm.ServiceCode, Price = sm.Price, ServiceDescription = sm.ServiceDescription });
                   
                }
                ticketsList[i].Services = Services;
	        }
            BookingModel bm = (BookingModel) Session["booking"];
            bm.Tickets = ticketsList;
            Session["booking"] = bm;
                return RedirectToAction("Bookingsummary", "Shoppingcart");
            
        
        }


   
        public ActionResult Bookingsummary()
        {
            BookingModel bm = (BookingModel)Session["booking"];

            return View(bm);
        }



        [HttpPost]
        public ActionResult Bookingsummary(FormCollection collection)
        {

            BookingModel bm = (BookingModel)Session["booking"];
            List<TicketModel> tickets = bm.Tickets;
           
            bm.ContactName = (string)collection["contactName"];
            bm.ContactNo = (string)collection["contactNo"];
            bm.ContactEmailAddress = (string)collection["contactEmail"];
           
            //TODO handle if fail
            //remove blocked seat, change status to ok then save.
            //it's better to make them in one transaction block
          
            foreach (TicketModel tm in tickets)
            {
               
                seatRep.CancelBlockFlightSeat(tm.FlightSeat.FlightSeatId); //cancel blocked seat
                
                //set status to ok and set flightSeatId to be 0, so when it save to db, it will use index
                tm.FlightSeat.Status = "ok";
                tm.FlightSeat.FlightSeatId = 0;
               
            }
            bm.Tickets = tickets;
            bm.BookingCode = "";
            string resultBookingCode = bookingRep.CreateBooking(Mapper.FromModel(bm));

            Session["booking"] = BookingRepository.GetBooking(resultBookingCode).ToModel();

            if (resultBookingCode != null)
            {
                Session["isBookingSucc"] = true;
                Session["bookingResultMessage"] = "Congratulations, Booking Successful! Please remember your booking code is " + resultBookingCode;
            }
            else
            {
                Session["isBookingSucc"] = false;
                Session["bookingResultMessage"] = "Sorry, Booking Failed! Please try again next time...";
            }
            return RedirectToAction("Bookingresult", "Shoppingcart");
          
        }

        public ActionResult Bookingresult()
        {
            ViewData["bookingResultMessage"] = (string)Session["bookingResultMessage"];
            ViewData["isBookingSucc"] = (Boolean)Session["isBookingSucc"];
            return View();
        }

       

        [NonAction]
        private void LoadData()
        {//TODO check those session if they are null, if null then use below code
            if (Session["seatType"] == null) {

                Session["seatType"] = "EC";
            }
            

            List<PassengerModel> passengers = new List<PassengerModel>();

            if (Session["PassengersList"] == null)
            {
                PassengerModel p1 = new PassengerModel();
                p1.FirstName = "a1";
                p1.LastName = "b1";
                p1.DateOfBirth = DateTime.Now.AddYears(-20);
                p1.PassportExpiryDate = DateTime.Now.AddYears(3);
                p1.TitleCode = "Mr";
                p1.PassportNo = "12234558";

                PassengerModel p2 = new PassengerModel();
                p2.FirstName = "a2";
                p2.LastName = "b2";
                p2.DateOfBirth = DateTime.Now.AddYears(-23);
                p2.PassportExpiryDate = DateTime.Now.AddYears(3);
                p2.TitleCode = "Ms";
                p2.PassportNo = "12234557";

                PassengerModel p3 = new PassengerModel();
                p3.FirstName = "a3";
                p3.LastName = "b3";
                p3.DateOfBirth = DateTime.Now.AddYears(-30);
                p3.PassportExpiryDate = DateTime.Now.AddYears(3);
                p3.TitleCode = "Mr";
                p3.PassportNo = "12234556";

                
                passengers.Add(p1);
                passengers.Add(p2);
                //passengers.Add(p3);

            }
            else
            {
                passengers = (List<PassengerModel>)Session["PassengersList"];

            }

            List<FlightModel> flights = new List<FlightModel>();
            if (Session["FlightsList"] == null)
            {

                FlightModel flightDepart = new FlightModel();

                flightDepart.FlightId = 2;
                 flightDepart = flightRep.GetFlightByFlightId(flightDepart.FlightId).ToModel();
                
                /*
                 * flightDepart.FlightCode = "SP001";
                flightDepart.FlightId = 1;
                flightDepart.TaxSurcharge = 300;
                departureairport
    arrivalAirport
    departureDateTime
    arrivalDateTime
    departureTerminal
    arrivalTerminal
                */
                FlightModel flightReturn = new FlightModel();

                flightReturn.FlightId = 67;
                flightReturn = flightRep.GetFlightByFlightId(flightReturn.FlightId).ToModel();
                
                
                flights.Add(flightDepart);
                flights.Add(flightReturn);

            }
            else
            {
                flights = (List<FlightModel>)Session["FlightsList"];

            }
            //above get from previous pages or create manually
            CustomerModel customer = null;
            if (Session["customer"] != null)
            {
                customer = (CustomerModel)Session["customer"];
            }
            String seatTypeCode =  (string)Session["seatType"];
            List<TicketModel> ticketsList = new List<TicketModel>();

            int flightIndex = -1;
            foreach (FlightModel fm in flights)
            {
                flightIndex++;

                foreach (PassengerModel pm in passengers)
                {
                   
                    TicketModel tm = new TicketModel();
                    tm.Passenger = pm;
                    tm.Flight = fm;
                    tm.FlightId = fm.FlightId;
                    
                    AircraftDTO aircraftDto = seatRep.getAircraftByFlightId(tm.FlightId);
                    tm.Flight.AircraftId = aircraftDto.AircraftId;
                   //if previous pages already return this, can remove above 2 lines
                    if (flightIndex == 0)
                    {
                        tm.isDeparture = true;
                    }
                    else
                    {
                        tm.isDeparture = false;
                    }
                    
                    //get ticketPrice by seatType flightId
                    tm.TicketFare = seatRep.GetFlightPriceByFlightIdSeatTypeCode(fm.FlightId,seatTypeCode);
                    ticketsList.Add(tm);
                }

            }
            BookingModel bm = new BookingModel();
            bm.BookingDate = DateTime.Now;
            bm.PaymentDue = DateTime.Now.AddDays(10);
            bm.Tickets = ticketsList;
            if (flights.Count >1)
            {
                bm.TripCode = "RoundTrip";
            }
            else
            {
                bm.TripCode = "OneWayTrip";
            }

            int adultCount = 0;
            int childCount = 0;
            DateTime currentDateTime = DateTime.Now;
            foreach (PassengerModel pm in passengers)
            {
                if (pm.DateOfBirth.AddYears(12) > currentDateTime)
                {
                    adultCount++;
                }
                else
                {
                    childCount++;
                }
            }
            bm.AdultNo = adultCount;
            bm.ChildNo = childCount;

            bm.Status = "Reserved";
            if (customer != null)
            {
                bm.CustomerId = customer.CustomerId;
            }

            Session["booking"] = bm;
           
           
            //end load data
        }

    }
}
